#include "Server.h"
#include <signal.h>


Server::Server()
			   : io_service_(),
			   acceptor_(io_service_),
			   connection_manager_(),
			   new_connection_(),
			   stopped_(true),
			   last_update_time(0),
			   update_timer_(io_service_,boost::posix_time::milliseconds(100))
{
	LogFunctionEnter;

	// Register to handle the signals that indicate when the Server should exit.
	// It is safe to register for the same signal multiple times in a program,
	// provided all registration for the specified signal is made through Asio.
}

void Server::startAccept()
{
	LogFunctionEnter;

	stopped_ = false;
 	new_connection_.reset(connection_template->span(io_service_,this));
	acceptor_.async_accept(new_connection_->socket(),
		boost::bind(&Server::handleAccept, this,
		boost::asio::placeholders::error));
}

void Server::handleAccept(const boost::system::error_code& e)
{
	LogFunctionEnter;

	if (stopped_)
		return;

	// Check whether the Server was stopped by a signal before this completion
	// handler had a chance to run.
	if (!acceptor_.is_open())
	{
		LOG_WARNING << "handleAccept but close!";
		return;
	}

	if (!e)
	{
		connection_manager_.start(new_connection_);
	}

	startAccept();
}

void Server::stop()
{
	stopped_ = true;
}

void Server::handleStop()
{
	LogFunctionEnter;

	// The Server is stopped by cancelling all outstanding asynchronous
	// operations. Once all operations have finished the io_service::run() call
	// will exit.
	acceptor_.close();
	connection_manager_.stop_all();
	update_timer_.cancel();
	stopped_ = true;
}

void Server::run()
{
	LogFunctionEnter;

	// The io_service::run() call will block until all asynchronous operations
	// have finished. While the Server is running, there is always at least one
	// asynchronous operation outstanding: the asynchronous accept call waiting
	// for new incoming connections.
	
	last_update_time = getMsTime();
	doUpdate();
	update_timer_.expires_from_now(boost::posix_time::milliseconds(100));
	update_timer_.async_wait(boost::bind(&Server::onUpdate,this,boost::asio::placeholders::error));

	// 	uint32 prve_time = getMsTime();
	// 	uint32 time_diff = 0;
	// 	uint32 current_time = 0;
	// 	int sleep_time =0;
	// 	uint32 x = uint32(-1);

	//while (!stopped_)
	io_service_.run();

// 	uint32 prve_time = getMsTime();
// 	uint32 time_diff = 0;
// 	uint32 current_time = 0;
// 	int sleep_time =0;
// 	uint32 x = uint32(-1);
// 
// 
// 	while (!stopped_)
// 	{
// 		current_time = getMsTime();
// 		
// 		if (current_time < prve_time)
// 		{
// 			time_diff = uint32(-1) - prve_time + current_time;
// 		}
// 		else
// 			time_diff = current_time - prve_time;
// 
// 		//LOG_INFO << "time_diff: " << time_diff;
// 
// 		connection_manager_.update(time_diff);
// 		io_service_.poll();
// 
// 		prve_time = current_time;
// 
// 		sleep_time = 100 - (getMsTime() - prve_time);
// 		//LOG_INFO << "sleep_time: " << sleep_time;
// 		if (sleep_time > 0)
// 			sleep(sleep_time);
// 	}

	LogFunctionLeave;
}

void Server::onConnClosed(ConnectionPtr c)
{
	connection_manager_.stop(c);
	return ;
}

void Server::onUpdate(const boost::system::error_code& error)
{
	if (stopped_ || error)
	{
		handleStop();
		return;
	}

	if (!error)
	{
		//LOG_INFO << "onUpdate";

		doUpdate();
		update_timer_.expires_from_now(boost::posix_time::milliseconds(100));
		update_timer_.async_wait(boost::bind(&Server::onUpdate,this,boost::asio::placeholders::error));
	}
}

void Server::doUpdate()
{
	if (stopped_)
	{
		handleStop();
		return;
	}

	uint32 current_time = getMsTime();
	uint32 time_diff = 0;
	if (current_time < last_update_time)
	{
		time_diff = uint32(-1) - last_update_time + current_time;
	}
	else
		time_diff = current_time - last_update_time;

	connection_manager_.update(time_diff);
}